package cn.iocoder.yudao.module.ao.controller.admin.vocationalclassschedule;

import cn.hutool.core.util.StrUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;

import cn.iocoder.yudao.module.ao.controller.admin.vocationalclassschedule.vo.*;
import cn.iocoder.yudao.module.ao.dal.dataobject.vocationalclassschedule.VocationalClassScheduleDO;
import cn.iocoder.yudao.module.ao.service.vocationalclassschedule.VocationalClassScheduleService;
import cn.iocoder.yudao.module.ao.service.vocationalclassschedule.VocationalClassScheduleExcelParser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;

import org.apache.poi.ss.usermodel.*;
import org.springframework.web.multipart.MultipartFile;
import lombok.extern.slf4j.Slf4j;

@Tag(name = "管理后台 - 中高技班级课")
@RestController
@RequestMapping("/ao/vocational-class-schedule")
@Validated
@Slf4j
public class VocationalClassScheduleController {
    @Resource
    private VocationalClassScheduleService vocationalClassScheduleService;

    @Resource
    private VocationalClassScheduleExcelParser excelParser;

    @Resource
    private AdminUserService adminUserService;

    @Resource
    private PermissionService permissionService;

    @PostMapping("/create")
    @Operation(summary = "创建中高技班级课")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:create')")
    public CommonResult<Long> createVocationalClassSchedule(@Valid @RequestBody VocationalClassScheduleSaveReqVO createReqVO) {
        return success(vocationalClassScheduleService.createVocationalClassSchedule(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新中高技班级课")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:update')")
    public CommonResult<Boolean> updateVocationalClassSchedule(@Valid @RequestBody VocationalClassScheduleSaveReqVO updateReqVO) {
        vocationalClassScheduleService.updateVocationalClassSchedule(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除中高技班级课")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:delete')")
    public CommonResult<Boolean> deleteVocationalClassSchedule(@RequestParam("id") Long id) {
        vocationalClassScheduleService.deleteVocationalClassSchedule(id);
        return success(true);
    }

    @DeleteMapping("/delete-list")
    @Parameter(name = "ids", description = "编号", required = true)
    @Operation(summary = "批量删除中高技班级课")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:delete')")
    public CommonResult<Boolean> deleteVocationalClassScheduleList(@RequestParam("ids") List<Long> ids) {
        vocationalClassScheduleService.deleteVocationalClassScheduleListByIds(ids);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得中高技班级课")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:query')")
    public CommonResult<VocationalClassScheduleRespVO> getVocationalClassSchedule(@RequestParam("id") Long id) {
        VocationalClassScheduleDO vocationalClassSchedule = vocationalClassScheduleService.getVocationalClassSchedule(id);
        return success(BeanUtils.toBean(vocationalClassSchedule, VocationalClassScheduleRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得中高技班级课分页")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:query')")
    public CommonResult<PageResult<VocationalClassScheduleRespVO>> getVocationalClassSchedulePage(@Valid VocationalClassSchedulePageReqVO pageReqVO) {
        // 权限控制:普通老师只能查看自己相关的课表
        applyTeacherScheduleFilter(pageReqVO);
        
        PageResult<VocationalClassScheduleDO> pageResult = vocationalClassScheduleService.getVocationalClassSchedulePage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, VocationalClassScheduleRespVO.class));
    }

    /**
     * 应用教师课表权限过滤器
     * 普通老师(角色ID=160)只能查看:
     * 1. 自己作为班主任的班级课表(class_teacher匹配)
     * 2. 自己授课的课表(课程字段中包含自己名字)
     */
    private void applyTeacherScheduleFilter(VocationalClassSchedulePageReqVO pageReqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId == null) {
            return;
        }

        AdminUserDO user = adminUserService.getUser(userId);
        if (user == null) {
            return;
        }

        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(userId);
        boolean isTeacher = roleIds.contains(160L);
        boolean isAdmin = roleIds.contains(1L);

        if (isTeacher && !isAdmin) {
            String teacherName = user.getRemark();
            
            if (StrUtil.isNotBlank(teacherName)) {
                // 设置教师名称过滤条件
                pageReqVO.setTeacherName(teacherName);
            } else {
                // 如果没有配置教师姓名,设置不可能匹配的值
                pageReqVO.setTeacherName("__NO_TEACHER__");
            }
        }
        // 管理员不做限制
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出中高技班级课 Excel")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportVocationalClassScheduleExcel(@Valid VocationalClassSchedulePageReqVO pageReqVO,
                                                   HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<VocationalClassScheduleDO> list = vocationalClassScheduleService.getVocationalClassSchedulePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "中高技班级课.xls", "数据", VocationalClassScheduleRespVO.class,
                BeanUtils.toBean(list, VocationalClassScheduleRespVO.class));
    }

    @PostMapping("/get-sheet-names")
    @Operation(summary = "获取Excel文件中的工作表名称")
    @Parameter(name = "file", description = "Excel 文件", required = true)
    public CommonResult<List<String>> getSheetNames(@RequestParam("file") MultipartFile file) {
        try {
            if (file == null || file.isEmpty()) {
                return success(new ArrayList<>());
            }

            List<String> sheetNames = new ArrayList<>();
            try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
                for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                    Sheet sheet = workbook.getSheetAt(i);
                    if (sheet != null) {
                        sheetNames.add(sheet.getSheetName());
                    }
                }
            }

            log.info("成功获取工作表名称，文件: {}, 工作表: {}", file.getOriginalFilename(), sheetNames);
            return success(sheetNames);
        } catch (Exception e) {
            log.error("获取工作表名称失败", e);
            // 返回默认工作表名称，而不是抛出异常
            List<String> defaultSheets = new ArrayList<>();
            defaultSheets.add("Sheet1");
            return success(defaultSheets);
        }
    }

    @GetMapping("/get-import-template")
    @Operation(summary = "获得导入中高技班级课模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        List<VocationalClassScheduleRespVO> list = new ArrayList<>();

        VocationalClassScheduleRespVO template = new VocationalClassScheduleRespVO();
        template.setTerm("2024-2025学年 第二学期");
        template.setClassName("25年春体验班");
        template.setClassSection("早1 08:00-08:20");
        template.setMondayCourse("语文 张老师 A101");
        template.setTuesdayCourse("数学 李老师 A102");
        template.setWednesdayCourse("英语 王老师 A103");
        template.setThursdayCourse("物理 赵老师 A104");
        template.setFridayCourse("化学 陈老师 A105");
        template.setSaturdayCourse("体育 刘老师 操场");
        template.setSundayCourse("自习 值班老师 教室");
        template.setClassTeacher("彭平");
        template.setClassroom("B215");

        list.add(template);

        ExcelUtils.write(response, "中高技班级课导入模版.xls", "数据", VocationalClassScheduleRespVO.class, list);
    }

    @PostMapping("/import")
    @Operation(summary = "导入中高技班级课")
    // @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')") // 暂时注释权限控制
    @Parameter(name = "file", description = "Excel 文件", required = true)
    @Parameter(name = "updateSupport", description = "是否支持更新，默认为 false", example = "true")
    @Parameter(name = "sheetName", description = "工作表名称", required = false)
    public CommonResult<VocationalClassScheduleImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                      @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                      @RequestParam(value = "sheetName", required = false) String sheetName) throws Exception {
        log.info("开始导入Excel文件，文件名: {}, 工作表: {}, 更新支持: {}", file.getOriginalFilename(), sheetName, updateSupport);

        // 使用新的解析器来解析复杂的课程表格式
        List<VocationalClassScheduleImportExcelVO> list = excelParser.parseExcel(file.getInputStream(), sheetName);
        log.info("Excel解析完成，解析到 {} 条数据", list.size());

        return success(vocationalClassScheduleService.importVocationalClassScheduleList(list, updateSupport));
    }

    @PostMapping("/clean-invalid-teacher-data")
    @Operation(summary = "清理无效的教师数据")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> cleanInvalidTeacherData() {
        try {
            vocationalClassScheduleService.cleanInvalidTeacherData();
            return success("无效教师数据清理完成");
        } catch (Exception e) {
            log.error("清理无效教师数据失败", e);
            return CommonResult.error(500, "清理失败: " + e.getMessage());
        }
    }

    @PostMapping("/clean-invalid-teacher-subjects")
    @Operation(summary = "清理教师信息中的无效科目")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> cleanInvalidTeacherSubjects() {
        try {
            vocationalClassScheduleService.cleanInvalidTeacherSubjects();
            return success("教师无效科目清理完成");
        } catch (Exception e) {
            log.error("清理教师无效科目失败", e);
            return CommonResult.error(500, "清理失败: " + e.getMessage());
        }
    }

    @PostMapping("/clean-invalid-course-data")
    @Operation(summary = "清理无效的课程数据")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> cleanInvalidCourseData() {
        try {
            vocationalClassScheduleService.cleanInvalidCourseData();
            return success("无效课程数据清理完成");
        } catch (Exception e) {
            log.error("清理无效课程数据失败", e);
            return CommonResult.error(500, "清理失败: " + e.getMessage());
        }
    }

    @PostMapping("/force-extract-all-teachers")
    @Operation(summary = "强制提取所有可能的教师姓名")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> forceExtractAllTeachers() {
        try {
            vocationalClassScheduleService.forceExtractAllPossibleTeachers();
            return success("教师强制提取完成");
        } catch (Exception e) {
            log.error("强制提取教师失败", e);
            return CommonResult.error(500, "提取失败: " + e.getMessage());
        }
    }

    @PostMapping("/test-course-creation")
    @Operation(summary = "测试课程创建功能")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> testCourseCreation() {
        try {
            vocationalClassScheduleService.testCourseCreation();
            return success("课程创建测试完成，请查看日志");
        } catch (Exception e) {
            log.error("测试课程创建失败", e);
            return CommonResult.error(500, "测试失败: " + e.getMessage());
        }
    }

    @PostMapping("/test-position-based-teacher-extraction")
    @Operation(summary = "测试基于位置的教师提取逻辑")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> testPositionBasedTeacherExtraction() {
        try {
            vocationalClassScheduleService.testPositionBasedTeacherExtraction();
            return success("基于位置的教师提取测试完成，请查看日志");
        } catch (Exception e) {
            log.error("测试基于位置的教师提取失败", e);
            return CommonResult.error(500, "测试失败: " + e.getMessage());
        }
    }

    @PostMapping("/scan-and-supplement-missing-data")
    @Operation(summary = "扫描并补充遗漏的科目和教师数据")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> scanAndSupplementMissingData() {
        try {
            vocationalClassScheduleService.scanAndSupplementMissingData();
            return success("扫描补充完成，请查看课程信息管理和教师信息管理模块");
        } catch (Exception e) {
            log.error("扫描补充数据失败", e);
            return CommonResult.error(500, "扫描失败: " + e.getMessage());
        }
    }

    @PostMapping("/extract-courses-by-position")
    @Operation(summary = "基于位置的智能课程信息提取")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> extractCoursesByPosition() {
        try {
            vocationalClassScheduleService.extractCoursesByPosition();
            return success("基于位置的课程信息提取完成，请查看课程信息管理、教师信息管理和上课场地信息管理模块");
        } catch (Exception e) {
            log.error("基于位置的课程信息提取失败", e);
            return CommonResult.error(500, "提取失败: " + e.getMessage());
        }
    }

    @PostMapping("/test-new-format-recognition")
    @Operation(summary = "测试新的格式识别逻辑")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> testNewFormatRecognition() {
        try {
            vocationalClassScheduleService.testNewFormatRecognition();
            return success("新的格式识别逻辑测试完成，请查看日志和各管理模块");
        } catch (Exception e) {
            log.error("测试新的格式识别逻辑失败", e);
            return CommonResult.error(500, "测试失败: " + e.getMessage());
        }
    }

    @PostMapping("/test-single-segment-course-validation")
    @Operation(summary = "测试一段式课程验证逻辑")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:import')")
    public CommonResult<String> testSingleSegmentCourseValidation() {
        try {
            vocationalClassScheduleService.testSingleSegmentCourseValidation();
            return success("一段式课程验证逻辑测试完成，请查看日志和课程信息管理模块");
        } catch (Exception e) {
            log.error("测试一段式课程验证逻辑失败", e);
            return CommonResult.error(500, "测试失败: " + e.getMessage());
        }
    }

    @GetMapping("/has-weekend-data")
    @Operation(summary = "检查是否有周末课程数据")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:query')")
    public CommonResult<Boolean> hasWeekendCourseData() {
        try {
            boolean hasWeekendData = vocationalClassScheduleService.hasWeekendCourseData();
            log.info("控制器检查周末数据结果: {}", hasWeekendData);
            return success(hasWeekendData);
        } catch (Exception e) {
            log.error("检查周末课程数据失败", e);
            return CommonResult.error(500, "检查失败: " + e.getMessage());
        }
    }

    @GetMapping("/debug-weekend-data")
    @Operation(summary = "调试周末课程数据")
    @PreAuthorize("@ss.hasPermission('ao:vocational-class-schedule:query')")
    public CommonResult<String> debugWeekendData() {
        try {
            // 查询所有记录来调试
            VocationalClassSchedulePageReqVO pageReq = new VocationalClassSchedulePageReqVO();
            pageReq.setPageNo(1);
            pageReq.setPageSize(1000); // 查询前1000条记录

            PageResult<VocationalClassScheduleDO> pageResult = vocationalClassScheduleService.getVocationalClassSchedulePage(pageReq);
            List<VocationalClassScheduleDO> allData = pageResult.getList();
            int totalCount = allData.size();
            int weekendCount = 0;
            StringBuilder debug = new StringBuilder();

            debug.append("总记录数: ").append(totalCount).append("\n");

            for (VocationalClassScheduleDO item : allData) {
                boolean hasSaturday = item.getSaturdayCourse() != null && !item.getSaturdayCourse().trim().isEmpty();
                boolean hasSunday = item.getSundayCourse() != null && !item.getSundayCourse().trim().isEmpty();

                if (hasSaturday || hasSunday) {
                    weekendCount++;
                    debug.append("ID: ").append(item.getId())
                         .append(", 班级: ").append(item.getClassName())
                         .append(", 节次: ").append(item.getClassSection())
                         .append(", 周六: [").append(item.getSaturdayCourse()).append("]")
                         .append(", 周日: [").append(item.getSundayCourse()).append("]\n");
                }
            }

            debug.append("有周末数据的记录数: ").append(weekendCount);

            log.info("调试周末数据:\n{}", debug.toString());
            return success(debug.toString());
        } catch (Exception e) {
            log.error("调试周末课程数据失败", e);
            return CommonResult.error(500, "调试失败: " + e.getMessage());
        }
    }

}